احدى أكثر الميزات في البيرل اذ لم تكن من افضل الميزات وهي الوسائل الكثيره لمعالجه النصوص وعلى راسها RE تسمى ايضاًُ بالـ regex أو regexp ، تعرف التعبيرات المنتظمة بأنها صيغة للبحث عن النمط (patterns) ليجاد واستخراج التطابق في النصوص ، حيث ان النمط عبارة عن مجموعة من الاحرف المراد البحث عنها في النصوص او في سطر النصوص ومع لغة البيرل فهو الاحرف المتضمنة مع slash /...../ فمثلاً
/def/
الكلمة def تمثل النمط ، في حال كان لدينا النصوص "redefine" فأن النمط في هذه الحالة يطابق الحرف الثالث d والحرف الرابع e والحرف الخامس f .
هناك مؤثرين للمطابقة وهما
=~ يسترجع في التعبير قيمة الصواب true اذا النص فعلاً مطابق وغير ذلك فهو يعيد false
!~ فهو عكس السابق اي بتحدد الغير مطابق فقط.
#!usr/bin/perl
$input_text = "two pints of milk and a pot of yoghurt";
if ($input_text=~/milk/) {
print "found";
}
else {
print "not found";
}
من الملاحظ انها حالة حساسة جداً في عملية المطابقة لذا لو ان الاحرف كانت Milk فسوف يسترجع القيمة false
من الممكن استخدام عملية المطابقة مع المتغير الخاص $_ والغالب يستخدم بكثره في البيرل
#!usr/bin/perl
$_ = "two pints of milk and a pot of yoghurt";
if (/milk/) {
print "found";
}
else {
print "not found";
}
مثال اخر لادخال النص المطابق للمستخدم وذلك لإجراء تجربة النمط المطابقة سوف تستخدم لاحقاً مع مختلف الانماط اسفل
#!usr/bin/perl -w $input = <>; $p = 'pass'; print "Yes, got a match \n" if $input =~ /$p/;
توفر البيرل حروف خاصة داخل النمط التي تمكنك لمطابق اي رقم واي حرف وهنا بعض الحالات :
| الحرف | الوصف |
|---|---|
| . | (اي حرف يطابق ماعدا السطر الجديد (حرف فقط |
| ^ | في بداية السطر او النصوص |
| $ | في نهاية السطر او النصوص |
| * | لاشئ او اكثر من الحرف الاخير |
| + | واحد او اكثر من الحرف الاخير |
| ? | لاشئ او واحد من الحرف الاخير |
يجب ان توضع هذة الاحرف الخاصة داخل النمط /.../ والتالي بعض الامثلة :
/t.e/ يمكن ان تكون the او tre او tle .. الى غير ذلك ولكن لايطابق te او tale
/^f/ هل f في بداية السطر
/^ftp/ في بداية السطر ftp
/e$/ في نهاية السطر e
/tle$/ في نهاية السطر tle
/^def$/ مطابقة فقط def
/un*d/ يطابق لاشئ او اكثر من الحرف الاخير n ، ويمكن ان يطابق ud او und او unnd... الخ
/un+d/ يطابق واحد اواكثر في اخر حرف n ويمكن ان يطابق und او unnd او unnnd .... الخ ولايمكن ان يطابق ud
/un?d/ يطابق لاشئ او واحد من الحرف الاخير n ويمكن ان يطابق ud او und او uud ولايمكن ان يطابق unnd
ا
/r+/ الابتداء بالحرف r ثم يلية اي عدد من المررات من r يمكن ان يطابق r, rr, rrr, rrrr, … وهذا يكافى النمط r+ = rr*
/.*/ اي نص ( غير السطر الجديد ) ، وهذا بسبب . يتوقع اي شئ ماعدا السطر الجديد و * يعني لاشئ او اكثر من حرف
/^$/ السطر الذي لاشئ فيه
تستعمل لاكثر من خيار ومطابقة اي حرف في هذا النطاق:
الرمز - يشير الى "بين"
الرمز ^ على البداية يعني "ليس"
امثله :
[0123456789] اما 0 او 1 او 2 ...... 9
[0-9] نفس السابق .
[qjk] اما q او j او k
[^qjk] ليس q ولا j ولا k
[a-z] اي حرف من a الى z (حروف صغيرة)
[^a-z] ليس من الحروف الصغيرة
[a-zA-Z] اي حرف من الحروف
[a-z]+ اي مجموعة احرف صغيرة مع الضرورة وجود حرف على الاقل .
علامات الحصر (.......) يمكن ان تستعمل لتجميع الاشياء معاً ، والرمز | فهو يمثل " او "
امثلة :
jelly|cream اما jelly او cream
(eg|le)gs اما eggs او legs
(da)+ اما da او dada او dadada .......
وهنا بعض من الرموز الخاصة
| السلسة | الوصف | المماثل |
|---|---|---|
| \w | اي حرف او رقم او underscores | [a-zA-Z0-9_] |
| \W | عكس السابق | [^a-zA-Z0-9_] |
| \d | اي رقم | [0-9] |
| \D | عكس السابق | [^0-9] |
| \s | whitespaceكالمسافة او السطر الجديد .... الخ | [ \r\t\n\f] |
| \S | whitespace بدون حرف | [^ \r\t\n\f] |
| \b | المطابق على حد الكلمة word boundary ، (لايوضع في الاقواس [] ) | |
| \B | عكس السابق | |
| \A | المطابق في بداية السطر | ^ |
| \Z | المطابق في نهاية السطر | $ |
امثلة:
/\bdef/ المطابقة فقط اذا كانت def في بداية الكلمة ، هذا يعني انها تطابق def و defghi لكن ليس abcdef .
/def\b/ المطابقة اذا كانت def في نهاية الكلمة ، تطابق def وabcdef وليس defghi
/\bdef\b/ يطابق فقط def ، وليس abcdef و defghi .
/\bis\b/ يطابق فقط is ، مثلاً يطابق النص " A tulip is a flower " لكن لايطابق مع "A worm isn't"
/\Bdef/ عكس السابق ، يطابق abcdef ، ولايطابق def و defghi .
/\Bdef\B/ يطابق cdefg و abcdefghi ، وليس def و defghi و abcdef .
سلسة \b , \B بدون توقف كما هي دالة split التي سيتم ذكرها لاحقاً في هذا الجزء ان شاء الله :
#!/usr/bin/perl
$thecount = 0;
print ("Enter the input here:\n");
$line = <STDIN>;
while ($line ne "")
{
if ($line =~ /\bthe\b/) {
$thecount += 1;
}
$line = <STDIN>;
}
print ("Number of lines containing 'the': $thecount\n");
Enter the input here: Now is the time for all good men to come to the aid of the party. ^D Number of lines containing 'the': 3
ولتجاهل الرمز الخاص كال $, |, [, ), \, / فاذا اردت مطابقة اي من تلك الرموز استعمل backslash
\| # Vertical bar \[ # An open square bracket \) # A closing parenthesis \* # An asterisk \^ # A carat symbol \/ # A slash \\ # A backslash
بعض الامثله:
[01] اما 0 او 1
\/0 القسمة بواسطة الصفر "/0"
\/ 0 القسمة بالصفر مع فراغ "/ 0"
\/\s0 القسمة بالصفر مع whitespace حيث يمكن ان space او tab ... الخ .
\/ *0 القسمة بالصفر مع احتمال ان تكون هناك بعض الفراغات كال "/0" او "/ 0" ...الخ .
\/\s*0 القسمة بالصفر مع احتمال ان تكون هناك بعض whitespace
\/\s*0\.0* كاسابق لكن مع النقطة العشرية كا "/0." و "/0.0" و "/0.00" ....الخ "/ 0." و "/ 0.0" .....الخ.
تستطيع تحديد المدى للحرف وكم عدد الاحرف التي تريد حدوثها باستعمال رمز { }
امثلة :
/de{1,3}f/ المطابقة كحد ادني حرف 1 وحد الاقصى 3 حروف للحرف e، و يمكن ان تطابق def, deef, deeef ولايمكن ان تطابق df,deeeef .
/de{3}f/ تحديد حد الحرف e ثلاثة تماماً ، يطابق deeef
/de{3,}f/ لتحديد العدد الادني للحرف e على الاقل 3 .
/de{0,3}f/ لتحديد العدد الاقصى للحرف e ، ليس اكثر من ثلاثة e.
/[a-z]{1,3}/ حرف او 2او 3 من الحروف الصغيرة
/.{3}/ اي ثلاثة حروف .
#!/usr/bin/perl
print ("Enter a number:\n");
$number = <STDIN>;
chop ($number);
if ($number =~ /^-?\d+$|^0[xX][\da-fA-F]+$/) {
print ("$number is a legal integer.\n");
}
else {
print ("$number is not a legal integer.\n");
}
Enter a number: 0x3ff1 0x3ff1 is a legal integer.
نلاحظ انها تقوم بالفحص اذا كان الرقم المدخل صحيح في السطر،فالتعبير المنتظم مجزاء الى جزئين :
^-?\d+$ للقيم العشرية
^0[xX][\da-fA-F]+$ للقيم السادس عشر
^ للفحص من بداية السطر .
-? واحد او لاشئ ، للتاكد من وجود الأشارة السالبة للعدد -
0 ليقودنا الى 0
[xX] اما x او X
[\da-fA-F]+اما واحد او اكثر من رقم او حرف من a الى f او A الى F .
$ لإغلاق النمط والتأكد من التطابق الصحيح للعدد .
البيرل تدعم التكرارات في النمط فمثلاً
/[\da-z]+[:;][\da-z]+[:;][\da-z]+/فنلاحظ ان النمط يستعمل بتكرار ، هناك طريقة اسهل في البيرل للتضمين جزء من النمط في الذاكرة وعند الحاجة اليه يتم استداعاء الجزء ،فعندما نستعمل مع رموز علامات الحصر ( ... ) النمط او جزء النمط يخزن في الذاكرة
([\da-z]+)يخزن هنا مفسر البيرل جزء النمط في الذاكرة ، وعند استدعى جزء النمط نستعمل فقط \n، حيث يمثل n الرقم المخزن في الذاكرة ، على سبيل المثال النمط المكتوب اعلى يمكن ان يكتب بالشكل التالي :
/([\da-z]+)[:;]\1[:;]\1/ايضاً من الممكن تخزين[:;] في الذاكرة ليصبح النمط كالتالي
/([\da-z]+)([:;])\1\2\1/التخزين في الذاكرة يتم من اليسار الى اليمين ، وذلك يعني ان 1 يمثل جزء النمط [\da-z]+ ، و 2 يمثل جزء النمط [:;] .
تلميح:
التخزين في الذاكرة لايهتم بالحرف الخاصة فمثلاً لو اردنا مطابقة التأريخ dd-mm-yy
/\d{2}([\W])\d{2}\1\d{2}/
يمكن ان يطابق
12-05-92
26.11.87
07 04 92
ولكن على اية حال 21-05.91 لايطابق .
في السابق استخدمنا محدد delimiter الانماط // فذلك يختصر من كتابة معامل المطابقة m// الى مطابقة النمط ونستطيع كتابة مطابقة النمط بدون او بإستخدام المعامل m ، كما يمكن استبدال اشكال المعامل وأستخدام محددات مختلفة مثل m<…> او m(…) او m{…} او m!…! او m"…"
المثال التالي يوضح ذلك عندما نرغب في مطابقة /u/jqpublic/perl/prog1
/\/u\/jqpublic\/perl\/prog1/من الضرورة ان تجاهل الرمز / فمن السهل استخدام معامل m مع محدد مختلف مثل !
m!/u/jqpublic/perl/prog1!عندما يطابق سلسة من الانماط في الذاكرة فانها تخزن قيمة النمط في موقع كل جزء ،ويمكننا الوصول الى تلك القيمة بإستخدام المتغيرات $n ، حيث n هو مجموعة الانماط المخزنة
فعلى سبيل المثال لمطابقة الاعداد الحقيقية floating-point بدون استعمال الاسية في الترقيم
$string = "This string contains the number 25.11."; $string =~ /-?(\d+)\.?(\d+)/; $integerpart = $1; $decimalpart = $2;
هذا يعني ان 25 تخصص للمتغير الاول ، 11 تخصص للمتغير الثاني ، وتستطيع استعمال المتغير الخاص $& لإستراجاع كل المتغيرات (يخزن فيه المطابقة الصحيحة)
$string = "This string contains the number 25.11."; $string =~ /-?(\d+)\.?(\d+)/; $number = $&;
في هذا الحالة يخصص المتغير number بالقيمة 25.11 .
مثال اخر
$_ = 'http://www.perl.org/index.html';
if(m#^http://([^/]+)(.*)#) {
print "host = $1\n"; # host = www.perl.org
print "path = $2\n";# path = /index.html
}
الاسبقية في مؤثرات النمط
| الاسبقية | الوصف |
|---|---|
| () | Pattern memory |
| + * ? {} | Number of occurrences |
| ^ $ \b \B | Pattern anchors |
| | | Alternatives |
هناك عده خيارات للنمط لسيطرة على كيفية مطابقة النمط ، فكل الخيارات تأتي بعد النمط ويمكنك تحدد اكثر من خيار وكما تريد :
| الخيار | الوصف | |
|---|---|---|
| g | مطابقة العديد من المرات وكل الأنماط المحتملة | Global match |
| i | حالة غيرحساسة لحالة الحرف | Case insensitive |
| m | معالجة النص مع العديد من السطور ، ويسمح للـanchors لمطابقة قبل وبعد السطر الجديد | Treat text as multiple lines |
| o | تقدير النمط فقط مرة واحدة | Compile once |
| s | معالجة النص كسطر وحيد ، ويسمح للاسطرالجديدة للمطابقة | Treat string as single line |
| x | يسمح للـ whitespace في النمط | Expanded regular expression |
| c | الموقع المحتفظ في اخر مطابقة عند الفشل (هو فقط مع الخيار g ) |
الخيار g
فأذا كان النمط مع الخيار g سوف يحدد مجموعة مع كل المطابقات الصحيحة ، فعلى سبيل المثال اذا اردنا مطابقة الكلمة balata
@matches = "balata" =~ /.a/g;
الان سوف تخزن في مصفوفة مطابقات بشكل ("ba", "la", "ta") ، ففي البداية يخصص العنصرالاول بالـ ba في اول مطابقة صحيحة ثم يخصص العنصر الثاني بثاني مطابقة صحيحة ...الى انتهاء عملية مطابقة النمط .
#!/usr/bin/perl
while ("balata" =~ /.a/g) {
$match = $&;
print ("$match\n");
}
استعملنا التكرار لتخصيص المطابقة الصحيحة للمتغير وطباعتة ، ثم الانتقال للمطابقة الثاني ... الى الإنتهاء (المتغير الخاص $& يقوم بعمل نسخ للمطابقة الحالية ، ايضاً المتغير الخاص $` للمطابقات السابقة ، $' للمطابقات التالية ) .
ba la ta
ولايجاد موقع المطابقة للنص عندما الخيار g يحدد نستخدم الدالة pos فهي تعيد بداية موقع المطابقة التالية (حيث يبداء البحث من بداية النص )
$offset = pos($string);
وعند استعمال الدالة بالطرف الايسار فذلك يعني انة سوف يبداء البحث من ذلك الموقع المحدد
pos($string) = $newoffset;
الخيار i يحدد حالة الحرف اما بحروف صغيرة او كبيرة مثل /de/i يطابق الكلمات de او dE او De او DE .
على سبيل المثال رغبنا في وضع قائمة الاوامر يدخلها المستخدم مثل "send", "abort", "list", "edit"يضع المستخدم احدها لكن أسبقية كل امر على الاخر بحسب الترتيب :
chomp($answer = <>);
if ("SEND" =~ /^\Q$answer/i) { print "Action is send\n" }
elsif ("STOP" =~ /^\Q$answer/i) { print "Action is stop\n" }
elsif ("ABORT" =~ /^\Q$answer/i) { print "Action is abort\n" }
elsif ("LIST" =~ /^\Q$answer/i) { print "Action is list\n" }
elsif ("EDIT" =~ /^\Q$answer/i) { print "Action is edit\n" }
الخيار m يخبر البيرل لمعالجة النص مع العديد من السطور ،فعندما الخيار يحدد مع الحرف الخاص ^ فهذا يعني انة سيبحث في بداية النص او في كل بداية سطر جديد
/^Th/m وهو مطابق This pattern matches\nThe first word on the second line
ومع الحرف الخاص $ يطابق في كل نهاية للسطر الجديد فمثلاً
/line.$/m
يطابق This is the end of the first line.\nHere's another line.
الخيار o فهو يمكنك من اخبار البيرل بالتقدر النمط فقط مرة واحدة في وقت التجميع فعلى سبيلي المثال
#!/usr/bin/perl $var = 1; $line =; while ($var < 10) { $result = $line =~ /$var/o; $line = ; $var++; }
فاولأ سوف تخصص القيمة 1 الى المتغير var ،ثم مفسر البيرل ينظر الى النمط ويستبدل المتغير بالقيمة أي يصبح النمط /1/ ، فالخيار oسوف يحتفظ بهذة القيمة وحتي وان تغير المتغير var يبقي في هذة الحالة /1/ ،فاذا كان الخيار o غير موجود فان النمط سوف يتغير الى /2/ .. /3/ .. /9/ ، ولاحظ ان قيمة المتغير result سوف يحوي القيمة 1 اذا كانت المطابقة صحيحة او true
الخيار s
وعند تحديد الخيار s فأن المعالجة على النص تسمح للاسطر الجديدة ، فعلى سبيل المثال الحرف الخاص للنمط dot لايطابق السطر الجديد "ضمن سطر فقط او وحيد" ، فأذا كان لديك اسطر جديدة في النص واردت dot من مطابقتهم فعليك تحدد الخيار s
$_ = "I saw Barney\ndown at the bowling alley\nwith Fred\nlast night.\n";
if (/Barney.*Fred/s) {
print "That string mentions Fred after Barney!\n";
}
وبدون الخيار لان يطابق بسبب ان dot لايطابق السطر الجديد .
الخيار x يسمح بإظافة whitespace داخل النمط ليصبح اسهل للقراءة فمثلاً
/-?\d+\.?\d*/ # what is this doing?
/ -? \d+ \.? \d* /x # a little better
# يمكن وضع التعليقات
/
-? # an optional minus sign
\d+ # one or more digits before the decimal point
\.? # an optional decimal point
\d* # some optional digits after the decimal point
/x # end of pattern
هي كالـ sed في اليونكس فمفسر البيرل يسمح بتبديل النص بنص اخر باستخدام معامل التبديل s/// فمثلاًُ نريد ابدال Barney بي Frd
#!/usr/bin/perl
$_ = "He's out bowling with Barney tonight.";
s/Barney/Frd/; # Replace Barney with Frd
print "$_\n";وفاذا كانت المطابقة خاطئة لان يحدث شيء، وهنا بعض الابدلات الاخرى
$_ = "green scaly dinosaur"; s/(\w+) (\w+)/$2, $1/;# Now it's "scaly, green dinosaur" s/^/huge, /; # Now it's "huge, scaly, green dinosaur" s/,.*een//; # Empty replacement: Now it's "huge dinosaur" s/green/red/; # Failed match: still "huge dinosaur" s/\w+$/($`!)$&/; # Now it's "huge (huge !)dinosaur" s/\s+(!\W+)/$1 /; # Now it's "huge (huge!) dinosaur" #يمكن تغير s/// برمز اخر S#huge#gigantic#; # Now it's "gigantic (huge!) dinosaur"
في الامثلة السابقة لربما لاحظت ان s/// تقوم بإستبدال واحد فقط حتي اذا كان البقية مطابق ،فالخيار /g يعمل على إستبدال كل مطابق .
$_ = "home, sweet home! homepage"; s/home/cave/g; print "$_\n"; # "cave, sweet cave! cavepage"
ولمنع التداخل
$_ = "home, sweet home! homepage"; s/\bhome\b/cave/g; print "$_\n"; # "cave, sweet cave! homepage"
واذا اردت استبدال whitespace من بداية ونهاية السطر
s/^\s+//; # Replace leading whitespace with nothing s/\s+$//; # Replace trailing whitespace with nothing # او بخطوة واحدةلكن باقل سرعة s/^\s+|\s+$//g; # Strip leading, trailing whitespace
بنفس خيارات المطابقة الاخرى تستعمل مع الإبدال ، مع اضافة خيار اضافي e الذي يعالج النص البديل كتعبير ويقدر قبل الاستبدال
$string = "0abc1"; $string =~ s/[a-zA-Z]+/$& x 2/e;
المطابقة /[a-zA-Z]+/ تطابق abc وتخزن في $& ثم يقدر التعبير $& x 2 والناتج abcabc ، ثم تسبدل abc بالناتج abcabc ، هذا يعني ان القيمة الجديدة للمتغير string هي 0abcabc1
هي طريقة اخرى لإستبدال حرف من مجموعة أحرف باستعمال معامل الترجمة tr/// او y/// وهو الاسرع للبحث عن حرف من مجموعة الاحرف
tr/string1/string2/
فاول حرف من string1 يستبدل بأول حرف من string2 وثاني حرف مع ثاني حرف ...وهكذا ، فعلى سبيل المثال :
$string = "abcdefgxxcba"; $string =~ tr/abc/def/; $string =~ tr/[a-z]/[A-Z]/; $string =~ tr/\t\n/ /; $string =~ tr/a-nA-Nm-zM-Z/m-zM-Za-nA-N/;استبدال النصف الاول مع الثاني
اذا كان قائمة النصوص الايسر اطول من الايمن فسوف يكرر الحرف الاخير على سبيل المثال :
$string = "abcdefgh"; $string =~ tr/efgh/abc/; # abcdabcc
فالغالب معامل الترجمة يستعمل للتحويل بين الاحرف الصغيرة والكبيرة ، فعند استعمال نفس الحرف في قائمة من الاحرف يستبدل باول حرف:
$string =~ tr/AAA/XYZ/; #replaces A with X $vowel_count = $string =~ tr/ae//;# لاعادة عدد الاحرف المستبدلة
توفر الترجمة القياسية ثلاث خيارات هي (c, d, s) التي تعدل من طبيعة الترجمة
الخيار c او compliment modifier فهو يعكس المعني الذي يتضمن كل الاحرف ماعدا القائمة المراد البحث عنها ، على سبيل المثال للإستبدال كل الارقام او الرموز او whitespace ماعدا السطر الجديد بعلامة ؟
$string =~ tr/a-zA-Z\n/?/c;
الخيار d او delete modifier يزيل اي حرف محدد في قائمة البحث ، فاذا كان نص البحث اطول من نص الاستبدال ، تستبدل بدون اي امتداد .
$string =~ tr/efgh/abc/d; # abcdab
الخيار s او squash modifier يزيل الحرف المكرر مرتين او اكثر في الناتج واخرجة بحرف واحد فقط،علىسبيل المثال
$text =~ tr/\t\n/ /s; # translate any whitespace to literal space and remove resulting duplicates
يمكن استعمال الثلاثة الخيارات كمجموعة مع بعضهم البعض ، فعلى سبيل المثال لإستبدال اي حرف( ماعدا الارقام ) بافراغ مع إزلة الفراغات المتكررة .
$string =~ tr/0-9/ /cs;
لديها ثلاثة وسطاء ومع الوسيط الاول تبحث عن النمط المطابق ويمكن ان يتضمن هذا الوسيط اما بعلامات اقتباس فردية او مضاعفة ، وطبيعياً فان التعبيرات المنتظم في هذة الدالة ليس واضح جداً كالاستعمالات العادية للنمط
الشكل العادي للدالة split
$text = " ,two pints of , milk and a pot of yoghurt\n";
# تقسيم النص الى قطعتين ,
@values = split (',',$text);
فنمط البحث فقط سيطابق رمز comma , ، ويمكن ان يستبدل التعبير بحذف الـــ whitespace من القيم الراجعه للعنصر المصفوفة باستخدام
@values = split('\s*,\s*',$text); # مع علامة الاقتباس
@values = split /\s*,\s*/,$text; # بدون علامات الحصر
ولاحظ في هذا المثال لايعالج whitespace في بداية ونهاية النص ،كما هي مع المطابقة والابدال فادالة split تربط الى المتغير الخاص $_ اذا لم يتضمن نص للبحث علية ، ويمكن كتابة التعبير بوسيط واحد
@csv = split /,/; # split $_ on commas
فاذا كانت الدالة بدون اي وسيط ستاخذ المتغير الخاص $_ مع whitespace ، وباكثر دقة تاخذ النمط المسافة ' ' (التي هي خاصة فقط للدالة split ) التي لن تعيد قيمة فارغة في البداية، وهي مكافئة للـ \s+ و غير ذلك فلن تعيد قيمة فارغة اذا كانت النص يبداء مع whitespace :
# split $_ on whitespace, explicitly (leading whitespace returns an empty # value) @words = split /\s+/,$_; # split $_ on whitespace, implicitly (leading whitespace does not return an # empty value) @words = split; # The same as 'split' on its own @words = split ' ';
اذا كانت الرغبة لعمل split على بستعمال الفرغات ، نجهز مع regexp حرفي بدلاًُ من ذلك :
# split on individual spaces @words = split / /;
فالدالة split لاتستعمل المعاملات =~ او !~ فهي وظيفة سهلة مضافة باستعمال مطابقة regexp لكن الدالة split تقراء افضل بكثير من الكلمة المحجوزة join .
بسبب تعلق الدالة grep بالنمط ، فالدلتان تحولن المصفوفة الى مصفوفة اخرى ام بنتقال القيم او بمؤافقة شرط معين وذلك للتسهيل الكود ومعرفة تركيب استعمال هذة الدوال ، فبدلاً من استعمال التكرات foreach وwhile لتؤليد مصفوفة جديدة نستطيع ان نفعل ذلك بستعمال الدوال وبشكل افضل .
والصيغة تاخذ شكلين متكافين :
map EXPRESSION, LIST grep EXPRESSION, LIST map BLOCK LIST grep BLOCK LIST
فغرض EXPRESSION او BLOCK هو لتنفيذ كل عناصر المصفوفة ، والناتج يعاد الى المصفوفة الجديدة، فالـ map هي متعلقة بفهموم التكرار foreach ، اما grep هي للعائدة محتوى القائمة الجزئية للقائمة الاصلية و expression هذة الدالة يقدر اما بالقيمة true او false وهي متعلقة بفهوم التكرار while
الدالة map تستعمل للانتقال كل القيم في القائمة الى قائمة اخر، هنا مثال لمشاهد كيف تعمل بفرض اننا ناخذ مصفوفة اعداد صحيحة ونريد اعادة هذة القيم الى حروف باستعمال الدالة الخاصة chr
my @numbers = (80, 101, 114, 108);
my @characters;
foreach (@numbers) {
push @characters, chr $_;
}
print @characters;
وبنفس العمل يمكن استعمال الدالة map
my @characters = map (chr $_, @numbers);
او بستعمال صيغة BLOCK
my @characters = map {chr $_} @numbers;
فهذا الشئ مفيد بتقليص عدد الاسطر الى سطر واحد فباستعمال الدالة map سوف تعيد الناتج كمصفوفة ويمكن ان نرجع الناتج الى البرنامج الرئيسي بكفاءة :
#!/usr/bin/perl
# callsub.pl
use warnings;
use strict;
sub do_list {
my ($subref, @in) = @_;
return map { &$subref ($_) } @in;
}
sub add_one {
return $_[0] + 1;
}
$, = ",";
print do_list (\&add_one, 1, 2, 3); # prints 2, 3, 4
perldoc -f map
grep
أسم الدالة grep ماخوذة من الامر grep في اليونكس الذي عمله البحث في الملفات النصية ويعيد السطور المطابقة للنمط .ومفهومها مشابة في البيرل حيث يعيد القائمة المطابقة من القائمة الاصلية بمؤافقة شرط التطابق .
my @numerics = ();
while (<>) {
push @numerics, $_ if /^\d/;
}
print "@numerics\n"
@numerics = grep {/^\d/} <>
قابليت التعبيرات المنتظمة للتطبيق المتنوع في الحواسيب من اهم الاسباب الباعثة للنظريات الاحسابية formal language theory و automata theory وجزء رئيسي في االانظمة والبرمجيات وفي الاخير يوجد هنا بعض التعبيرات المنتظمة المفيدة اذا ارادت التعرف والاطلاع اكثر كتاب Mastering Regular Expressions O'Reilly و Perl Cookbook, 2nd Edition:
Check for valid currency value
^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(\.[0-9]{1,2})?$
Check for valid email address
^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$
Swap first two words
s/(\S+)(\s+)(\S+)/$3$2$1/
Keyword = Value
m/^(\w+)\s*=\s*(.*?)\s*$/ # keyword is $1, value is $2
Line of at least 80 characters
m/.{80,}/
او
length( ) >= 80 # ok, not a regex
MM/DD/YY HH:MM:SS
m|(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)|
Changing directories
s(/usr/bin)(/usr/local/bin)g
Expanding %7E (hex) escapes
s/%([0-9A-Fa-f][0-9A-Fa-f])/chr(hex($1))/ge
Deleting C comments (imperfectly)
s{
/* # Match the opening delimiter
.*? # Match a minimal number of characters
*/ # Match the closing delimiter
}{ }gsx;
Removing leading and trailing whitespace
s/^\s+//;
s/\s+$//;
Turning \ followed by n into a real newline
s/\\n/\n/g;
Removing package portion of fully qualified symbols
s/^.*:://
Dotted quads (most IP addresses)
# XXX: fails on legal IPs 127.1 and 2130706433.
m{
^ ( \d | [01]?\d\d | 2[0-4]\d | 25[0-5] )
\. ( \d | [01]?\d\d | 2[0-4]\d | 25[0-5] )
\. ( \d | [01]?\d\d | 2[0-4]\d | 25[0-5] )
\. ( \d | [01]?\d\d | 2[0-4]\d | 25[0-5] )
$
}x
Removing leading path from filename
s{^.*/}{ }
Extracting columns setting from TERMCAP
$cols = ( ($ENV{TERMCAP} || " ") =~ m/:co#(\d+):/ ) ? $1 : 80;
Removing directory components from program name and arguments
($name = " $0 @ARGV") =~ s{ /\S+/}{ }g;
Checking your operating system
die "This isn't Linux" unless $^O =~ m/linux/i;
Joining continuation lines in multiline string
s/\n\s+/ /g
Extracting all numbers from a string
@nums = m/(\d+\.?\d*|\.\d+)/g;
Finding all-caps words
@capwords = m/(\b\p{ Upper-case Letter }+\b)/g;
Finding all-lowercase words
@lowords = m/(\b\p{ Lower-case Letter }+\b)/g;
Finding initial-caps word
@icwords = m{
( \b
[\p{ Upper-case Letter }\p{ Title-case Letter }]
\p{ Lower-case Letter } *
\b )
}gx;
Finding links in simple HTML
@links = m/]+?HREF\s*=\s*["']?([^'" >]+?)['"]?\s*>/ig;
Finding middle initial in $_
$initial = /^\S+\s+(\S)\S*\s+\S/ ? $1 : "";
Changing double verticle prime pairs to curly quotes
s/"([^"]*)"/``$1''/g # old way
# next is unicode only
s/"([^"]*)"/\x{201C}\x{201C}$1\x{201D}\x{201D}/g
Extracting sentences (double spaces required between each)
{ local $/ = "";
while (<>) {
s/\n/ /g;
s/ {3,}/ /g;
push @sentences, m/(\S.*?[!?.])(?= {2}|\Z)/g;
}
}
YYYY-MM-DD
m/\b(\d{4})-(\d\d)-(\d\d)\b/ # YYYY in $1, MM in $2, DD in $3
North American telephone numbers
m/ ^
(?:
1 \s (?: \d\d\d \s)? # 1, or 1 and area code
| # ... or ...
\(\d\d\d\) \s # area code with parens
| # ... or ...
(?: \+\d\d?\d? \s)? # optional +country code
\d\d\d ([\s\-]) # and area code
)
\d\d\d (\s|\1) # prefix (and area code separator)
\d\d\d\d # exchange
$
/x
Exclamations
m/\boh\s+my\s+gh?o(d(dess(es)?|s?)|odness|sh)\b/i
Extracting lines regardless of line terminator
push(@lines, $1) while $input =~ s{
^ # gobble from front
(
. # begin $1: any single char (/s)
?* # but minimally matching even none
)
(?: # make capturing if saving terminators
\x0D \x0A # CRLF
| \x0A # LF
| \x0D # CR
| \x0C # FF
# (see http://www.unicode.org/reports/tr13/tr13-9.html)
| \x{2028} # Unicode LS
| \x{2029} # Unicode PS
)
}{ }sx; # consumes $input
Or use split:
@lines = split m{
(?: # make capturing if saving terminators
\x0D \x0A # CRLF
| \x0A # LF
| \x0D # CR
| \x0C # FF
# (see http://www.unicode.org/reports/tr13/tr13-9.html)
| \x{2028} # Unicode LS
| \x{2029} # Unicode PS
)
}x, $input;